<script>
  // 判断右边构造函数的原型对象是否存在于左边对象的原型链上
  function _instaceof(obj, ctor) {
    // 左边必须是对象
    /* 
       1 _instaceof Number -> false
       Number(1) _instaceof Number -> false
       new Number(1) _instaceof Number -> true
     */
    if (!(obj && typeof obj === 'object')) {
      return false
    }

    // 获取对象的原型链对象
    let proto = Object.getPrototypeOf(obj)
    // 判断对象的原型链对象是否是构造函数函数的原型对象
    return proto === ctor.prototype || _instaceof(proto, ctor)
  }


  // 测试
  let Fn = function () {}
  let p1 = new Fn()

  console.log(_instaceof({}, Object)) // true
  console.log(_instaceof(p1, Fn)) // true
  console.log(_instaceof({}, Fn)) // false
  console.log(_instaceof(null, Fn)) // false
  console.log(_instaceof(1, Fn)) // false
</script>